﻿/**
 * Project SEM 2 - SMS for schools
 * File author:ToanMH
 * Datetime create:14/11/2010
 * File version:1.0
 * File description:
 * 
 * Modify history:
 * 
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using org.smslib;
using System.Threading;
using org.smslib.modem;
using org.smslib.notify;
using DatabaseProvider;
using System.IO;
using System.Data.Sql;
using System.Data.SqlClient;
using LogHelper;
namespace sms_modem_control
{
    public partial class frmControler : Form
    {
        //Variable for thread control
        bool closeRequested = false;


        #region SMS Modem Control
        Thread thMain;//Thread running
        private Service srv;//Declate service
        private Comm2IP.Comm2IP com1;//declare com2ip
        private IPModemGateway gateway;//Declare gateway
        private bool isRunning=false;
        Thread thCom;
        Thread thSendMsg;
        ApplicationSettings appSetting;

        private string strComIP;
        private Int32 iComIPPort =0;
        private string strComName;
        private string strModemName;
        private string strModemManufacture;
        private org.smslib.AGateway.Protocols AgwProtocol;
        private ModemGateway.IPProtocols modemProtocol;
        private Int32 iComSpeed = 0;
        /// <summary>
        /// Load parameter form user setting
        /// </summary>
        private void loadParameter() {
            upDateMonitorBack("Loading parameter...", Color.BlueViolet);
            appSetting = new ApplicationSettings();
           
            
            strComName = appSetting.ComUserChose;
            Int32.TryParse(appSetting.ComSpeedUserChose,out iComSpeed);
            strModemName = appSetting.ModemNameUserChose;
            strModemManufacture = appSetting.ModemUserChose;

            upDateMonitorBack(" Manufacture: " + strModemManufacture, Color.Empty);
            upDateMonitorBack(" Modem name: " + strModemName, Color.Empty);

            upDateMonitorBack(" COM: " + strComName, Color.Empty);
            upDateMonitorBack(" Speed: " + iComSpeed, Color.Empty);

            strComIP = appSetting.ComIPUserChose;
            Int32.TryParse(appSetting.ComIPPortUserChose, out iComIPPort);
            upDateMonitorBack(" COM IP: " + strComIP+":"+iComIPPort, Color.Empty);
            
            //Load ipprotocol
            upDateMonitorBack(" IP protocol: " + appSetting.IPProtocolUserChose, Color.Empty);
            if (appSetting.IPProtocolUserChose.ToUpper().Equals("TEXT"))
            {
                modemProtocol = ModemGateway.IPProtocols.TEXT;
            }
            else if (appSetting.IPProtocolUserChose.ToUpper().Equals("BINARY"))
            {
                modemProtocol = ModemGateway.IPProtocols.BINARY;
            }
            //Load Modem protocol
            if (appSetting.ModemProtocolUserChose.ToUpper().Equals("TEXT"))
            {
                AgwProtocol = AGateway.Protocols.TEXT;
            }
            else if (appSetting.ModemProtocolUserChose.ToUpper().Equals("BINARY"))
            {
                AgwProtocol = AGateway.Protocols.PDU;
            }
            upDateMonitorBack(" Modem protocol: " + appSetting.ModemProtocolUserChose, Color.Empty);
            upDateMonitorBack("Loaded parameter.", Color.BlueViolet);
        }
        /// <summary>
        /// Init database
        /// </summary>
        private void initDatabase() {
            //Check the connection string is set
            try
            {
                upDateMonitorBack("Start install the connection to database.", Color.BlueViolet);
                if (MSSQL.ConnectionString == null || MSSQL.ConnectionString.Equals(""))
                {
                    MSSQL.ConnectionString = SQLHelper.getConntionStringFromXML(Path.GetDirectoryName(Application.ExecutablePath) + "\\Conf\\ConnectionConfig.xml");
                }
                //Make connection 
                MSSQL.ConnnectionObj = MSSQL.makeConnect();
                //Open connection
                MSSQL.openConnection();
                upDateMonitorBack("Installed.", Color.BlueViolet);
            }
            catch (Exception ex){
                upDateMonitorBack(ex.Message, Color.Red);
                Log.logTransaction(ex);
            }

        }
        /// <summary>
        /// Install services
        /// </summary>
       private void installServices(){
           try
           {
               upDateMonitorBack("Install service...", Color.Empty);
               srv = Service.getInstance();//Install service
               upDateMonitorBack("Installed.", Color.Empty);

               upDateMonitorBack("Install com to IP...", Color.Empty);
               com1 = new Comm2IP.Comm2IP(new byte[] { 127, 0, 0, 1 }, iComIPPort, strComName, iComSpeed);//install com to ip
               thCom = new Thread(new ThreadStart(com1.Run));
               upDateMonitorBack("Installed.", Color.Empty);

               upDateMonitorBack("Install modem gateway...", Color.Empty);
               gateway = new IPModemGateway("modem.com1", strComIP, iComIPPort, strModemManufacture, strModemName);//install modem gw
               upDateMonitorBack("Installed.", Color.Empty);

               //Init send messages thread
               thSendMsg = new Thread(new ThreadStart(SendMessageFromDB));
               
           }
           catch (Exception ex)
           {
               upDateMonitorBack(ex.Message, Color.Red);
               upDateMonitorBack(ex.StackTrace, Color.Red);
               Log.logTransaction(ex);
           }
       }

       /// <summary>
       /// Running service method
       /// </summary>
        public void DoIt()
        {
            //Load prameter
            loadParameter();
            //Call install service
            initDatabase();
            
            installServices();

            upDateMonitorBack("All install successfull", Color.BlueViolet);
            try
            {
                upDateMonitorBack("Starting GSM modem control... Please wait", Color.Empty);
                // Start the COM listening thread.
                upDateMonitorBack("Start COM to IP...", Color.Empty);
                thCom.Start();
                upDateMonitorBack("Started.", Color.BlueViolet);

                srv.setInboundMessageNotification(new InboundNotification());
                srv.setCallNotification(new CallNotification());
                srv.setGatewayStatusNotification(new GatewayStatusNotification());           
                gateway.setIpProtocol(ModemGateway.IPProtocols.BINARY);

                // Set the modem protocol to PDU (alternative is TEXT). PDU is the default, anyway...
                gateway.setProtocol(AGateway.Protocols.PDU);
                // Do we want the Gateway to be used for Inbound messages?
                gateway.setInbound(true);
                // Do we want the Gateway to be used for Outbound messages?
                gateway.setOutbound(true);
                // Let SMSLib know which is the SIM PIN.
                gateway.setSimPin("1234");
                gateway.setSmscNumber("+8491020005");
                // Add the Gateway to the Service object.
                srv.addGateway(gateway);

                upDateMonitorBack("Start Gateway service...", Color.Empty);
                srv.startService();
                upDateMonitorBack("Started.", Color.Empty);
                upDateMonitorBack("All services started.", Color.BlueViolet);
                // Printout some general information about the modem.
                upDateMonitorBack("Modem Information:", Color.BlueViolet);
                upDateMonitorBack("  Manufacturer: " + gateway.getManufacturer(), Color.Empty);
                upDateMonitorBack("  Model: " + gateway.getModel(), Color.Empty);
                upDateMonitorBack("  Serial No: " + gateway.getSerialNo(), Color.Empty);
                upDateMonitorBack("  SIM IMSI: " + gateway.getImsi(), Color.Empty);
                
                lblBattery.Text = gateway.getBatteryLevel()+"%";
                lblSignal.Text = gateway.getSignalLevel() +"db";

                gateway.setDisplayIllegalReceivedMessages(true);

                //gateway.sendUSSDRequest(new USSDRequest("*101#"));
                //string str = gateway.sendUSSDCommand("*101#");
                
               // upDateMonitorBack(str);

                upDateMonitorBack("Start send messages.", Color.Blue);
                thSendMsg.IsBackground = true;
                thSendMsg.Start();
            }
            catch (Exception e)
            {
                upDateMonitorBack(e.Message, Color.Red);
               // upDateMonitorBack(e.StackTrace);
                Log.logTransaction(e);
            }

        }
        /// <summary>
        /// Send messages
        /// </summary>
        public void SendMessageFromDB() {
            SqlDataReader reader = null; 
            try
            {
                //Get all message?
                //Should get 5 message per second but this query is get full
                string strSQLQuery =
                        "SELECT     tbl_sms_response.sms_response_id, tbl_sms_response.isdn_to, tbl_sms_response.smsc_number, tbl_sms_response.sms_content, tbl_sms_response.wap_url, " +
                        "      tbl_sms_encodings.sms_encoding_name, tbl_sms_response.date_time_sent, tbl_sms_response.flash_sms, tbl_sms_type.sms_type_name,tbl_sms_response.validity_period " +
                        " FROM         tbl_sms_encodings INNER JOIN " +
                        "      tbl_sms_response ON tbl_sms_encodings.sms_encoding_id = tbl_sms_response.sms_encoding_id INNER JOIN " +
                        "      tbl_sms_type ON tbl_sms_response.sms_type_id = tbl_sms_type.sms_type_id " +
                        " WHERE	tbl_sms_response.date_time_sent <=getDate() AND tbl_sms_response.sent_status=0";
                string strSQLUpdate = "update tbl_sms_response Set sent_status = {0} where sms_response_id= {1}";
                string strSQLUpdateTmp = "";
                //Init message type before loop to send message
                OutboundMessage msgShort = new OutboundMessage();
                OutboundBinaryMessage msgBin = new OutboundBinaryMessage();
                OutboundEncryptedMessage msgEncrypted; ;
                OutboundWapSIMessage msgWap;
                bool sendResult=false;
                while (!closeRequested)
                {
                    //Get records from sms_response 
                     reader = MSSQL.ExecuteCommandGetDataReader(strSQLQuery);

                    while (reader.Read())
                    {
                        long iStart = DateTime.Now.Ticks * 100 / 1000000;
                        if (reader.GetString(8).ToLower().Equals("short message"))
                        {
                            msgShort.setText(reader.GetString(3).Trim());
                            msgShort.setRecipient(reader.GetString(1).Trim());
                            msgShort.setEncoding(Message.getMessageEncodingByName(reader.GetString(5).Trim()));
                            msgShort.setFlashSms(reader.GetBoolean(7));
                            msgShort.setValidityPeriod(reader.GetInt32(9));
                            //gateway.setSmscNumber(reader.GetString(2).Trim());
                            //gui tin
                            upDateMonitorBack("Send short message to " + reader.GetString(1).Trim() + " content: " + reader.GetString(3), Color.Blue);
                            sendResult = srv.sendMessage(msgShort);
                            if (sendResult)//Thanh cong
                            {
                                strSQLUpdateTmp = String.Format(strSQLUpdate, 1, reader.GetInt64(0));
                                upDateMonitorBack("Sent successfull. Total: " + (DateTime.Now.Ticks * 100 / 1000000 - iStart) + " ms", Color.Blue);
                            }
                            else {//neu loi
                                strSQLUpdateTmp = String.Format(strSQLUpdate, 2, reader.GetInt64(0));
                                upDateMonitorBack("Sent failed. Total: " + (DateTime.Now.Ticks * 100 / 1000000 - iStart) + " ms", Color.DarkBlue);
                            }
                            iStart = DateTime.Now.Ticks * 100 / 1000000;
                            upDateMonitorBack("Update status for this message.", Color.Blue);
                            upDateMonitorBack("Updated " + MSSQL.ExecuteCommandNoneQuery(strSQLUpdateTmp) + " record(s). Total: " + (DateTime.Now.Ticks * 100 / 1000000 - iStart) + " ms", Color.Blue);
                             strSQLUpdateTmp = "";
                        }
                        else if (reader.GetString(8).ToLower().Equals("binary message"))
                        {

                        }
                        else if (reader.GetString(8).ToLower().Equals("encrypted message"))
                        {

                        }
                        else if (reader.GetString(8).ToLower().Equals("wap si message"))
                        {
                            
                            msgWap = new OutboundWapSIMessage(reader.GetString(1).Trim(),new java.net.URL("http",reader.GetString(4).Trim(),""), reader.GetString(3).Trim());
                            msgWap.setEncoding(Message.getMessageEncodingByName(reader.GetString(5).Trim()));
                            msgWap.setFlashSms(reader.GetBoolean(7));
                            
                            //gateway.setSmscNumber(reader.GetString(2).Trim());
                            upDateMonitorBack("Send wap message to " + reader.GetString(1).Trim() + " content: " + reader.GetString(3), Color.Blue);
                            srv.sendMessage(msgWap);
                            upDateMonitorBack("Sent successfull. Total: " + (DateTime.Now.Ticks * 100 / 1000000 - iStart) + " ms", Color.Blue);
                            iStart = DateTime.Now.Ticks * 100 / 1000000;
                            upDateMonitorBack("Update status for this message.", Color.Blue);
                            upDateMonitorBack("Updated " + MSSQL.ExecuteCommandNoneQuery(strSQLUpdate + " '" + reader.GetInt64(0) + "'") + " record(s). Total: " + (DateTime.Now.Ticks * 100 / 1000000 - iStart) + " ms", Color.Blue);

                        }                       
                       
                    }
                    Application.DoEvents();
                    Thread.Sleep(1000);//Sleep 1 seconds before continue
                    MSSQL.CloseDatabaseObject(reader);
                }
            }
            catch (Exception e)
            {
                upDateMonitorBack(e.Message, Color.Red);
                Log.logTransaction(e);
            }
            finally {
                MSSQL.CloseDatabaseObject(reader);
                try
                {
                    if(thSendMsg !=null)
                            thSendMsg.Abort();
                }
                catch (ThreadAbortException ex)
                {
                    Log.logTransaction(ex);
                }

            }
        }
        
        #endregion

        #region Delegate Update monitor
        /// <summary>
        /// Delegate to update status in monitor text
        /// </summary>
        /// <param name="strMonitorText"></param>
        delegate void upDateMonitor(string strMonitorText, Color cTextColor); //Used for threading  
        public void upDateMonitorBack(string strMonitorText,Color cTextColor)
        {
            if (!txtMonitor.InvokeRequired)
            {
                //Update text in monitor
                UIUtilities.AppendRichTextBox(txtMonitor, Color.Gray, System.DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss")+": ");
                UIUtilities.AppendRichTextBox(txtMonitor, cTextColor, strMonitorText + "\r\n");
               //Scroll bar to bottom help to easy monitor
                int min, max;
                UIUtilities.GetScrollRange(txtMonitor.Handle, UIUtilities.SB_VERT, out min, out max);
                //SendMessage(txtMonitor.Handle, UIUtilities.EM_SETSCROLLPOS, 0, new POINT(0, max - txtMonitor.Height));
                UIUtilities.SendMessage(txtMonitor.Handle, UIUtilities.EM_SETSCROLLPOS, 0, new sms_modem_control.UIUtilities.POINT(0, max - txtMonitor.Height + 5));
            }
            else
            {
                upDateMonitor progressD = new upDateMonitor(upDateMonitorBack);
                this.Invoke(progressD, new object[] { strMonitorText,cTextColor });
            }
        }

        #endregion

        #region FORM DESIGN
        /// <summary>
        /// Init form
        /// </summary>
        public frmControler()
        {
            //Set path for log file.
            Log.FileLogPath = Application.StartupPath+"\\System Log\\error.log";
            InitializeComponent();
        }
        #endregion

        #region FORM EVENTS
        /// <summary>
        /// Button Help click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnHelp_Click(object sender, EventArgs e)
        {

        }        
        /// <summary>
        /// Start run sms server 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// 
        private void btnStart_Click(object sender, EventArgs e)
        {
            closeRequested = false;//
            UIUtilities.AppendRichTextBox(txtMonitor, Color.DarkBlue, "SMS for schools - version 0.1 - Project SEM 2 in HANOI-APTECH \r\n");
            thMain = new Thread(new ThreadStart(DoIt));
            thMain.Start();
            thMain.IsBackground = true;
            

            btnStop.Enabled = true;
            btnStart.Enabled = false;
            isRunning = true;
        }

        #region Close service
        /// <summary>
        /// Close service method
        /// </summary>
        public void closeServices()
        {
            try

            {

                //Check ther service is running
             /*   if(gateway!=null)
                {
                    gateway.stopGateway();
                    gateway = null;
                }*/
                if (com1 != null)
                {
                    upDateMonitorBack("The service COM to IP is stopping...", Color.Empty);
                    com1.Stop();
                    com1 = null;
                    upDateMonitorBack("The service COM to IP is stoped.", Color.Empty);
                }
                else
                {
                    upDateMonitorBack("The service COM to IP is not running.",Color.Empty);
                }
                if (srv != null)
                {
                    upDateMonitorBack("The service Gateway is stopping...", Color.Empty);
                    srv.stopService();
                    srv = null;
                    upDateMonitorBack("The service Gateway is stoped.", Color.Empty);
                }
                else
                {
                    upDateMonitorBack("The service Gateway is not running.", Color.Empty);
                }
                if (thSendMsg != null)
                {
                    upDateMonitorBack("Stop the send messages thread...", Color.Empty);
                    thSendMsg.Abort();
                    thSendMsg = null;
                    upDateMonitorBack("Stopped.", Color.Empty);
                }
                else {
                    upDateMonitorBack("The send message is not running.", Color.Empty);
                }
                upDateMonitorBack("The services stoped", Color.Red);
            }
            catch (Exception ex)
            {
                upDateMonitorBack("Stop service is error\n" + ex.Message, Color.Red);
                Log.logTransaction(ex);
            }
            finally {
                
                isRunning = false;

                //Close connection to db
                MSSQL.CloseDatabaseObject(MSSQL.ConnnectionObj);
                 //Stop thread
                if (thCom != null) {
                    if (thCom.ThreadState != ThreadState.Suspended)
                        thCom.Abort();
                    else
                        thCom = null;
                }
                if (thStop != null)
                    if (thStop.ThreadState != ThreadState.Suspended)
                        thStop.Abort();
                    else
                        thStop = null;
                if (thMain != null)
                    if (thMain.ThreadState != ThreadState.Suspended)
                        thMain.Abort();
                    else
                        thMain = null;
            }
        }
        #endregion



        /// <summary>
        /// Button Stop click
        /// Stop servies
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        Thread thStop;
        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                closeRequested = true;
                upDateMonitorBack("Begin stopping services...Please wait !", Color.Chocolate);
                thStop = new Thread(new ThreadStart(closeServices));
                thStop.IsBackground = true;
                thStop.Start();
                
            }
            catch (Exception ex)
            {
                upDateMonitorBack(ex.Message, Color.Red);
                upDateMonitorBack(ex.StackTrace, Color.Red);
            }
            finally
            {
                
                btnStop.Enabled = false;
                btnStart.Enabled = true;
            }
        }


        /// <summary>
        /// Exit button click
        /// Destroy all thread is running.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmControler_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                Application.ExitThread();
                Application.Exit();
            }
            catch 
            {
                //Log
            }
            finally
            {
                this.Dispose();
            }

        }
        /// <summary>
        /// Form load 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmControler_Load(object sender, EventArgs e)
        {
            btnStart.Enabled = true;
            btnStop.Enabled = false;
        }       
        /// <summary>
        /// Battery change events
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lblBattery_TextChanged(object sender, EventArgs e)
        {
            if (lblBattery.Text.ToLower().Equals("0%")) {
                lblBattery.Image = global::sms_modem_control.Properties.Resources.Gnome_Battery_Caution_32;
            }
        }

       /// <summary>
       /// Show monitor process
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void btnViewLog_Click(object sender, EventArgs e)
        {
            frmSystemMonitor frmProcessMonitor = new frmSystemMonitor();
            frmProcessMonitor.Show();
        }

        /// <summary>
        /// Close program 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmControler_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isRunning)
            {
                MessageBox.Show("Please stop SMS modem service before close the program.","SMS modem control", MessageBoxButtons.OK,MessageBoxIcon.Warning);
                e.Cancel=true;
            }
            else {
                Application.ExitThread();
            }
           
        }

        /// <summary>
        /// Show form settings
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSetting_Click(object sender, EventArgs e)
        {
            frmSetting frmSet = new frmSetting();
            //If programe is running. Alert warning message
            if (isRunning)
            {
                if (MessageBox.Show("If program is running you canot apply new setting. The new setting will apply after you restart programe.\nDo you want to continue?", "SMS modem control", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    frmSet.ShowDialog();
                }
                else {
                    frmSet = null;
                }
            }
            else {
                frmSet.ShowDialog();
            }
        }
        #endregion






    }
}